#include <cstring>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <unordered_map>

void logStr(std::string_view str) { std::cout << str << std::endl; }

enum class MODE { PANDA, PERF, UNKNOWN };

int main(int argc, char *argv[]) {
  if (argc < 3) {
    logStr("missing arg: file name or mode(panda, perf)");
    return 1;
  }

  MODE mode = MODE::UNKNOWN;
  if (strcmp(argv[1], "--panda") == 0)
    mode = MODE::PANDA;
  else if (strcmp(argv[1], "--perf") == 0)
    mode = MODE::PERF;

  if (mode == MODE::UNKNOWN) {
    logStr("mode is not set correctly");
    return 1;
  }

  const char *inFileName = argv[2];
  std::cout << "inFileName: " << inFileName << std::endl;

  std::ifstream inFileStream(inFileName, std::ios_base::in);
  if (!inFileStream.is_open()) {
    std::cout << "failed to open " << inFileName << std::endl;
    std::cout << "current path" << std::filesystem::current_path() << std::endl;
    return 1;
  }

  char delimNumberSymbl = mode == MODE::PANDA ? ';' : ' ';
  std::unordered_map<std::string, unsigned long long> funcsFreq;
  unsigned long long totalCount = 0;
  for (std::string line; std::getline(inFileStream, line);) {
    auto delimPos = line.rfind(delimNumberSymbl);

    std::string freqStr = line.substr(delimPos + 1);
    ////std::cout << "freqStr: " << freqStr << std::endl;
    unsigned long long freq = std::stoull(freqStr); // include space
    totalCount += freq;
    auto stPos = line.rfind(';', delimPos - 1);
    if (stPos == std::string::npos) {
      stPos = 0;
    } else {
      ++stPos;
    }

    while (line[stPos] == ' ') {
      ++stPos;
    }

    std::string func = line.substr(stPos, delimPos - stPos);
    // std::cout << "func: " << func << std::endl;

    auto [it, res] = funcsFreq.try_emplace(std::move(func), freq);
    if (!res) {
      it->second += freq;
    }
  }

  inFileStream.close();

  std::multimap<unsigned long long, const std::string_view, std::greater<unsigned long long>> funcsFreqSorted;

  for (const auto &[fname, freq] : funcsFreq) {
    funcsFreqSorted.emplace(freq, fname);
  }

  std::string outFileName = inFileName;
  outFileName += "_sum.csv";
  std::ofstream outFileStream(outFileName, std::ios_base::out | std::ios_base::trunc);
  outFileStream << "Function name;Sample;%" << std::endl;
  outFileStream << std::setprecision(2);

  for (const auto &[freq, fname] : funcsFreqSorted) {
    outFileStream << fname << ";" << freq << ";"
                  << static_cast<long double>(freq) / static_cast<long double>(totalCount) * 100.0 << std::endl;
  }

  outFileStream.close();

  std::cout << std::setprecision(2) << "total: " << totalCount << std::endl;
  return 0;
}
